import G6 from '@antv/g6'
import { hexToRgba } from '@/utils/color.js'

/**
 * 分支边 - 专为分支节点设计的智能路径规划边
 * 能够根据节点位置信息自动生成避开其他节点的路径
 */
export default function () {
  G6.registerEdge('branchEdge', {
    setState(name, value, item) {
      const group = item?.getContainer()
      const children = group?.get('children')
      const stationEdge = children.find((item) => item.get('name') === 'branch-edge')
      const edgeHighlight = children.find((item) => item.get('name') === 'edge-highlight')

      stationEdge.attr('opacity', 1)
      edgeHighlight.attr('opacity', 0)

      switch (name) {
        case 'dark':
          stationEdge.attr('opacity', value ? 0.2 : 1)
          break
        case 'highlight':
          edgeHighlight.attr('opacity', value ? 1 : 0)
          break
      }
    },
    draw(cfg, group) {
      const startPoint = cfg.startPoint
      const endPoint = cfg.endPoint
      const sourceNode = cfg.sourceNode
      const targetNode = cfg.targetNode

      // 获取目标节点的位置信息（如果有）
      const positionInfo = targetNode?.positionInfo || {}
      const isBranchNode = targetNode?.isBrancheNode

      // 检测是否为闭环分支（分支节点连接回主干）
      const isClosedLoop = isBranchNode && sourceNode && targetNode && !sourceNode.isBrancheNode && targetNode.isBrancheNode && targetNode.mainTrunkNodeId !== undefined

      // 检测是否为分支到分支的连接
      const isBranchToBranch = sourceNode?.isBrancheNode && targetNode?.isBrancheNode

      // 构建路径
      let path = []

      // 如果是分支节点，使用智能路径规划
      if (isBranchNode) {
        // 获取角度和距离信息
        const angle = positionInfo.angle
        const distance = positionInfo.distance
        const isFallback = positionInfo.isFallback

        // 计算控制点 - 使用贝塞尔曲线实现平滑的路径
        // 根据角度和距离计算控制点位置
        if (angle !== undefined && distance !== undefined) {
          // 计算中间控制点，使曲线更平滑
          const midX = startPoint.x + (endPoint.x - startPoint.x) * 0.5
          const midY = startPoint.y + (endPoint.y - startPoint.y) * 0.5

          // 计算控制点偏移量 - 根据角度调整
          // 闭环分支或分支到分支连接使用更大的偏移比例
          const offsetRatio = isClosedLoop || isBranchToBranch ? 0.5 : 0.3
          const dx = (endPoint.x - startPoint.x) * offsetRatio
          const dy = (endPoint.y - startPoint.y) * offsetRatio

          // 根据角度调整控制点位置，使曲线避开主干方向
          let cp1x, cp1y, cp2x, cp2y

          // 闭环分支或后备位置使用更复杂的路径
          if (isClosedLoop || isBranchToBranch || isFallback) {
            // 使用三次贝塞尔曲线，增加一个中间点，避开可能的碰撞
            const angleRad = (angle * Math.PI) / 180
            const perpAngleRad = angleRad + Math.PI / 2

            // 计算垂直于连线方向的偏移 - 闭环分支使用更大的偏移
            const perpOffsetDist = distance * (isClosedLoop ? 0.4 : isBranchToBranch ? 0.35 : 0.25)
            const perpOffsetX = Math.cos(perpAngleRad) * perpOffsetDist
            const perpOffsetY = Math.sin(perpAngleRad) * perpOffsetDist

            // 设置控制点，使曲线避开中间区域
            cp1x = startPoint.x + dx + perpOffsetX
            cp1y = startPoint.y + dy + perpOffsetY
            cp2x = endPoint.x - dx + perpOffsetX
            cp2y = endPoint.y - dy + perpOffsetY

            // 对于闭环分支，进一步调整控制点以避开主干
            if (isClosedLoop) {
              // 增加控制点的弯曲程度，使曲线更加远离主干
              const extraOffset = distance * 0.15
              cp1x += perpOffsetX * 0.5
              cp1y += perpOffsetY * 0.5
              cp2x += perpOffsetX * 0.5
              cp2y += perpOffsetY * 0.5
            }
          } else {
            // 标准情况下的控制点计算
            cp1x = startPoint.x + dx
            cp1y = startPoint.y + dy
            cp2x = endPoint.x - dx
            cp2y = endPoint.y - dy
          }

          // 构建贝塞尔曲线路径
          path = [
            ['M', startPoint.x, startPoint.y],
            ['C', cp1x, cp1y, cp2x, cp2y, endPoint.x, endPoint.y],
          ]
        } else {
          // 如果没有角度和距离信息，使用简单的曲线
          path = [
            ['M', startPoint.x, startPoint.y],
            ['L', endPoint.x, endPoint.y],
          ]
        }
      } else {
        // 非分支节点使用直线
        path = [
          ['M', startPoint.x, startPoint.y],
          ['L', endPoint.x, endPoint.y],
        ]
      }

      // 创建边的形状
      const shapeConfig = {
        attrs: {
          cursor: 'pointer',
          stroke: cfg.color,
          path: path,
          lineWidth: 3, // 分支边线宽较细
          zIndex: 2,
          lineDash: cfg.style?.lineDash || null,
        },
        name: 'branch-edge',
      }

      const shape = group.addShape('path', shapeConfig)

      // 添加高亮效果层
      group.addShape('path', {
        ...shapeConfig,
        attrs: {
          ...shapeConfig.attrs,
          stroke: hexToRgba(cfg.color, 0.25),
          lineWidth: 9,
          opacity: 0,
        },
        name: 'edge-highlight',
        zIndex: 1,
      })

      return shape
    },
  })
}
